﻿@using System.ComponentModel.DataAnnotations
@using System.Net
@using Blazor.CoffeeTalesApi.Entity
@using Blazor.CoffeeTalesApi.Util
@using Blazor.Localization
@using Blazor.Model.Dto
@using Blazor.Model.Entity
@using Blazor.Services.Device
@using Blazor.Services.Update
@using Blazor.Validators
@using DynamicData
@inherits Blazor.Core.SoraniFeedbackComponentBase<WhitelistOptions, WhitelistResult?>
@inject IStringLocalizer<UpdateSettingLocalization> Loc
@inject ILogger<WhitelistModal> Logger
@inject IUpdateService UpdateService

<Form @ref="_form" Model="_model" LabelColSpan="8" WrapperColSpan="16" LabelAlign="AntLabelAlignType.Left">
    <FormItem Label="@Loc[UpdateSettingLocalization.WhitelistKeyType]">
        <Segmented @bind-Value="_selectedKeyType" Disabled="@((Options.Type & WhitelistOptions.EditType.Key) == 0)">
            <SegmentedItem Value="WhitelistKeyType.IP" Label="@Loc[UpdateSettingLocalization.IP]"/>
            <SegmentedItem Value="WhitelistKeyType.DeviceId" Label="@Loc[UpdateSettingLocalization.DeviceId]"/>
        </Segmented>
    </FormItem>
    @switch (_selectedKeyType)
    {
        case WhitelistKeyType.IP:
        {
            <FormItem Label="@Loc[UpdateSettingLocalization.IP]">
                <Input @bind-value="@context.IP" Disabled="@((Options.Type & WhitelistOptions.EditType.Key) == 0)"/>
            </FormItem>
            <FormItem WrapperColOffset="8">
                <Button Type="ButtonType.Link" OnClick="FillWithMyIpClickHandler" Disabled="@((Options.Type & WhitelistOptions.EditType.Key) == 0)">
                    @Loc[UpdateSettingLocalization.FillWithMyIp]
                </Button>
            </FormItem>
            break;
        }
        case WhitelistKeyType.DeviceId:
        {
            <FormItem Label="@Loc[UpdateSettingLocalization.DeviceId]">
                <AutoComplete @bind-Value="@context.DeviceId" Options="_options" Disabled="@((Options.Type & WhitelistOptions.EditType.Key) == 0)" OnSelectionChange="SelectDeviceHandler"/>
            </FormItem>
            break;
        }
        default:
            throw new ArgumentOutOfRangeException();
    }
    <FormItem Label="@Loc[UpdateSettingLocalization.RawResourceVersion]">
        <Input @bind-value="@context.Raw" Disabled="@((Options.Type & WhitelistOptions.EditType.Raw) == 0)"/>
    </FormItem>

    <FormItem Label="@Loc[UpdateSettingLocalization.DefaultResourceVersion]">
        <Input @bind-value="@context.Default" Disabled="@((Options.Type & WhitelistOptions.EditType.Default) == 0)"/>
    </FormItem>

    <FormItem Label="@Loc[UpdateSettingLocalization.VersionComment]">
        <Input @bind-value="@context.Comment" Disabled="@((Options.Type & WhitelistOptions.EditType.Comment) == 0)"/>
    </FormItem>
</Form>

@code {
    private class FormData
    {
        [IPAddress]
        public string IP { get; set; } = string.Empty;

        [Guid]
        public string DeviceId { get; set; } = string.Empty;

        [Required]
        public string Raw { get; set; } = string.Empty;
        [Required]
        public string Default { get; set; } = string.Empty;

        public string Comment { get; set; } = string.Empty;
    }

    private FormData _model = null!;
    private Form<FormData> _form;

    private WhitelistKeyType _selectedKeyType;

    private readonly List<string> _options = [];

    [Inject]
    private IDeviceService DeviceService { get; set; }

    [Parameter]
    public EventCallback<WhitelistOptions?>? OnResult { get; set; }

    protected override void OnInitialized()
    {
        _model = new FormData()
        {
            IP = Options.Key is IpKey ipKey ? ipKey.ToString() : string.Empty,
            DeviceId = Options.Key is DeviceIdKey deviceIdKey ? deviceIdKey.ToString() : string.Empty,
            Raw = Options.Raw,
            Default = Options.Default,
            Comment = Options.Comment,
        };
        _selectedKeyType = Options.Key switch
        {
            IpKey => WhitelistKeyType.IP,
            DeviceIdKey => WhitelistKeyType.DeviceId,
            _ => WhitelistKeyType.IP,
        };
        base.OnInitialized();
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        var devices = await DeviceService.GetAll();
        _options.AddRange(devices.Select(d => d.Description));
    }

    public override Task OnFeedbackOkAsync(ModalClosingEventArgs args)
    {
        if (!_form.Validate())
        {
            args.Reject();
            return Task.CompletedTask;
        }

        IWhitelistKey key = _selectedKeyType switch
        {
            WhitelistKeyType.IP => new IpKey(IPAddress.Parse(_model.IP)),
            WhitelistKeyType.DeviceId => new DeviceIdKey(_model.DeviceId),
            _ => throw new ArgumentOutOfRangeException()
        };

        var entry = new ResourceVersionEntry()
        {
            Raw = _model.Raw,
            Default = _model.Default,
            Comment = _model.Comment,
        };

        OkCancelRefWithResult.OkAsync(new WhitelistResult()
        {
            Key = key,
            Entry = entry
        });
        return Task.CompletedTask;
    }

    private async Task FillWithMyIpClickHandler()
    {
        var myIp = await UpdateService.FetchMyIpAsync();
        if (myIp is null)
        {
            _ = MessageService.Error(Loc[UpdateSettingLocalization.FailedToFetchMyIp].ToString());
            return;
        }

        _model.IP = myIp.ToString();
        StateHasChanged();
    }

    private async Task SelectDeviceHandler(AutoCompleteOption obj)
    {
        var value = obj.Value;

        if (value is not string name)
        {
            return;
        }

        var id = await DeviceService.GetId(name);
        if (id is null)
        {
            return;
        }

        _model.DeviceId = id.ToString()!;
        StateHasChanged();
    }
}